package com.bobo.web.provider.util.commutils;

import com.google.common.collect.Lists;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.SocketConfig;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.Charset;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * User: ellios Time: 14-4-25 : 下午5:12
 */
public class RestTemplateFactory {

    public final static Charset UTF8 = Charset.forName("UTF-8");

    private static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 1000;

    private static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 1000;

    private static final int DEFAULT_TIMEOUT = 1000;


    private static ClientHttpRequestFactory createRequestFactory(final int timeout) {
        int readTimeout = (timeout <= 0) ? DEFAULT_TIMEOUT : timeout;
        return new HttpComponentsClientHttpRequestFactory(create(readTimeout, 1000, 2 * readTimeout));
    }

    private static HttpClient create(int readTimeout, int connectTimeout, int requestTimeout) {
        PoolingHttpClientConnectionManager connectionManager
                = new PoolingHttpClientConnectionManager(3, TimeUnit.MINUTES);
        connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL_CONNECTIONS);
        connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_CONNECTIONS_PER_ROUTE);
        SocketConfig socketConfig = SocketConfig.copy(SocketConfig.DEFAULT)
                .setSoTimeout(readTimeout)
                .setSoReuseAddress(true)
                .setTcpNoDelay(true)
                .build();

        RequestConfig requestConfig = RequestConfig.copy(RequestConfig.DEFAULT)
                .setConnectionRequestTimeout(requestTimeout)
                .setConnectTimeout(connectTimeout)
                .setSocketTimeout(readTimeout)
                .build();

        // This HttpClient support compressing by default.
        HttpClientBuilder builder = HttpClients.custom()
                .setDefaultSocketConfig(socketConfig)
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager);

        return builder.build();
    }

    private static List<HttpMessageConverter<?>> getCustomHttpMessageConverter() {
        List<HttpMessageConverter<?>> converters = Lists.newArrayList();
        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
        jsonConverter.setSupportedMediaTypes(Lists.newArrayList(new MediaType("text", "html", UTF8),
                new MediaType("text", "plain", UTF8)));
//        converters.add(new VisJsonHttpMessageConverter());
        converters.add(jsonConverter);
        return converters;
    }

    private static RestTemplate createCustomRestTemplate() {
        RestTemplate template = new RestTemplate();
        List<HttpMessageConverter<?>> converters = template.getMessageConverters();
        converters.addAll(getCustomHttpMessageConverter());
        return template;
    }

    public static RestTemplate getTemplate() {
        RestTemplate template = createCustomRestTemplate();
        template.setRequestFactory(createRequestFactory(DEFAULT_TIMEOUT));
        return template;
    }

    public static RestTemplate getTemplate(int timeout) {
        RestTemplate template = getTemplate();
        template.setRequestFactory(createRequestFactory(timeout));
        return template;
    }
}
